﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mono.Cecil.Cil;
using Mono.Cecil;

namespace devtm.Aop.Emit
{

    public class TryFinallyCilWorker : CilWorker
    {

        private Label labelFinally;

        internal TryFinallyCilWorker(CilWorker parent)
            : base(parent)
        {

            ExceptionHandler = new ExceptionHandler(ExceptionHandlerType.Finally);

            cursor = parent.Current;
            labelFinally = DefineLabel();
            ExceptionHandler.TryStart = Start = Insert(OpCodes.Nop);

            // Instructions Try

            Insert(OpCodes.Leave_S, labelFinally);
            ExceptionHandler.TryEnd = ExceptionHandler.HandlerStart = Insert(OpCodes.Nop);

            // Instructions Catch

            ExceptionHandler.HandlerEnd = Insert(OpCodes.Nop);
            Insert(OpCodes.Endfinally);            
            ExceptionHandler.HandlerEnd = Insert(OpCodes.Nop);
            End = MarkLabel(labelFinally);
            //this.Body.ExceptionHandlers.Add(ExceptionHandler);

            cursor = TryStart;         

        }

        public Instruction TryStart { get { return ExceptionHandler.TryStart; } }
        public Instruction TryEnd { get { return ExceptionHandler.TryEnd; } }

        public Instruction HandlerStart { get { return ExceptionHandler.HandlerStart; } }
        public Instruction HandlerEnd { get { return ExceptionHandler.HandlerEnd; } }

        public ExceptionHandler ExceptionHandler { get; private set; }


        public TryCatchCilWorker CreateTryCatchBloc(Instruction InsertAfter, Type exceptionType)
        {
            TryCatchCilWorker cur = new TryCatchCilWorker(this, TryStart, InsertAfter, Body.Method.Module.Import(exceptionType));
            return cur;
        }
    }

}


/*
         
        [0] class [mscorlib]System.Exception ex)

t1      L_0001: nop
                // Instructions Try
            L_0008: nop
            L_0009: leave.s L_0016	->	goto label1
            L_000b: stloc.0
            L_000c: nop
                    // Instructions Cacht
            L_0013: nop
            L_0014: leave.s L_0016	->	goto label1

label1: L_0016: nop
        L_0017: leave.s L_0022	->	goto label2
t1      L_0019: nop
                // Instructions Finally
        L_0020: nop
        L_0021: endfinally

label2: L_0022: nop                                 

         
    .try L_0001 to L_000b catch [mscorlib]System.Exception handler L_000b to L_0016
    .try L_0001 to L_0019 finally handler L_0019 to L_0022

*/


/*
 
 .method public hidebysig instance void TryFinally() cil managed
{
    .maxstack 0

    L_0001: nop 
 
    L_0002: nop 
    L_0003: leave.s L_0008
    L_0005: nop 
    L_0006: nop 
    L_0007: endfinally 
    L_0008: nop 

    .try L_0001 to L_0005 finally handler L_0005 to L_0008

 

 * 
 */